/*
 *所有关于deviceinfo类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*deviceinfoService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using VOL.Core.BaseProvider;
using VOL.Core.Extensions.AutofacManager;
using VOL.Entity.DomainModels;
using System.Linq;
using VOL.Core.Utilities;
using System.Linq.Expressions;
using VOL.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using VOL.RadarDevice.IRepositories;
using OfficeOpenXml;
using VOL.Core.ManageUser;
using VOL.Core.DbContext;
using Newtonsoft.Json;
using SqlSugar;
using VOL.Entity.DomainModels.Devices.Dto;
using VOL.Core.Configuration;
using System.Collections;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using Microsoft.Extensions.Options;
using System.Text;
using VOL.Entity.DomainModels.Devices.MongoDbModels;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Text.Json;
using System.Collections.Generic;

namespace VOL.RadarDevice.Services
{
    public partial class deviceinfoService
    {
        WebResponseContent webResponse = new WebResponseContent();
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IdeviceinfoRepository _repository;//访问数据库
        private readonly IdevicedetailRepository _repositoryDetail;//访问数据库
        private readonly ImeasureinfoRepository _repositoryImeasure;//访问数据库
        private readonly IboardInfoRepository _repositoryBoardInfo;//访问数据库
        private readonly IdeviceShareRepository _repositorySharp;//访问数据库
        private readonly MongoDbContext _mongoDbContext;

        [ActivatorUtilitiesConstructor]
        public deviceinfoService(
            MongoDbContext mongoDbContext,
            IdeviceShareRepository repositorySharp,
            IdeviceinfoRepository dbRepository,
            IdevicedetailRepository repositoryDetail,
            IboardInfoRepository repositoryBoardInfo,
            ImeasureinfoRepository repositoryImeasure,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            _repositoryDetail = repositoryDetail;
            _repositoryImeasure = repositoryImeasure;
            _repositoryBoardInfo = repositoryBoardInfo;
            _mongoDbContext = mongoDbContext;
            _repositorySharp = repositorySharp;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }
        /// <summary>
        /// 下载模板(导入时弹出框中的下载模板)
        /// </summary>
        /// <returns></returns>
        public override WebResponseContent DownLoadTemplate()
        {
            //指定导出模板的字段,如果不设置DownLoadTemplateColumns，默认导出查所有页面上能看到的列(2020.05.07)
            DownLoadTemplateColumns = x => new { x.deviceNo };
            return base.DownLoadTemplate();
        }
        /// <summary>
        /// 列表查询
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public override PageGridData<deviceinfo> GetPageData(PageDataOptions options)
        {
            var deviceNo = "";
            int? isOnline = null;
            DateTime? startTime = null;
            DateTime? endTime = null;

            var listWhere = JsonConvert.DeserializeObject<List<OptionWheres>>(options.Wheres);
            foreach (var item in listWhere)
            {
                if (item.name == "deviceNo")
                    deviceNo = item.value;
                else if (item.name == "online" && !string.IsNullOrWhiteSpace(item.value))
                    isOnline = int.Parse(item.value);
                else if (item.name == "CreateDate" && item.displayType == "thanorequal")
                    startTime = DateTime.Parse(item.value);
                else if (item.name == "CreateDate" && item.displayType == "lessorequal")
                    endTime = DateTime.Parse(item.value);
            }
           
            int pageSize = options.Rows; // 每页显示的数量
            int pageIndex = options.Page; // 当前页码
            string sort =options.Sort;

            var querys = repository.FindAsIQueryable(r=>1==1).WhereIF(startTime.HasValue, m => m.CreateDate >= startTime.Value)
                .WhereIF(endTime.HasValue, m => m.CreateDate <= endTime.Value)
                .WhereIF(!string.IsNullOrWhiteSpace(deviceNo),d=>d.deviceNo.Contains(deviceNo))
                .WhereIF(isOnline!=null,d=>d.online== isOnline);

            var allowIds = AppSetting.QueryAllDeviceUserIds;
            if (!string.IsNullOrWhiteSpace(allowIds))
            {
                 var userId = UserContext.Current.UserId;
                 var strIds = allowIds.Split(',');
                 var ids =  Array.ConvertAll(strIds, int.Parse);
                if (!ids.Contains(userId))
                {
                    var sharpModels = _repositorySharp.FindAsIQueryable(r =>1==1).ToList();
                    List<deviceShare> shares = new List<deviceShare>();
                    foreach (var sharpModel in sharpModels)
                    {
                        var userIds = sharpModel.shareUserIds.Split(",");
                        if (userIds.Contains(userId.ToString()))
                        {
                            shares.Add(sharpModel);
                        }
                    }
                    var deviceIdList = shares.Select(r => r.deviceId).ToList();
                    querys = querys.Where(d=>d.CreateID ==  userId || deviceIdList.Contains(d.id));
                }
            }
            var dtos = querys;
            if (options.Order == "desc")
                dtos = querys.OrderByDescending(d=>d.online).OrderByDescending(d=>d.deviceNo).OrderByDescending(d=>d.runtime).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            else
                dtos = querys.OrderBy(d=>d.online).OrderBy(d=>d.deviceNo).OrderBy(d=>d.runtime).Skip((pageIndex - 1) * pageSize).Take(pageSize);

            PageGridData<deviceinfo> pageGridData = new PageGridData<deviceinfo>();
            var models = dtos.ToList();
            var deviceNos = models.Select(d=>d.deviceNo);
            //var items = _repositoryImeasure.FindAsIQueryable(m => deviceNos.Contains(m.deviceNo)).OrderByDescending(m => m.uploadTime).ToList();
            foreach (var model in models)
            {
                //var entity = items.OrderByDescending(m => m.uploadTime).First();
                var entity = _mongoDbContext.MeasureInfo.OrderByDescending(m => m.uploadTime).FirstOrDefault(m => m.deviceNo == model.deviceNo);
                if (entity != null)
                {
                    model.targetDistance1 = entity.targetDistance1;
                    model.targetDistance2 = entity.targetDistance2;
                    model.targetDistance3 = entity.targetDistance3;
                    model.targetSnr1 = entity.targetSnr1;
                    model.targetSnr2= entity.targetSnr2;
                    model.targetSnr3 = entity.targetSnr3;
                }
            }

            //var entitys = _mapper.Map<List<measureinfo>>(models);

            pageGridData.rows = models;
            pageGridData.total = querys.ToList().Count;

            GetPageDataOnExecuted?.Invoke(pageGridData);
            return pageGridData;
        }
        /// <summary>
        /// 导出处理
        /// </summary>
        /// <param name="pageData"></param>
        /// <returns></returns>
        public override WebResponseContent Export(PageDataOptions pageData)
        {
            var deviceNo = "";
            int? isOnline = null;
            DateTime? startTime = null;
            DateTime? endTime = null;

            var listWhere = JsonConvert.DeserializeObject<List<OptionWheres>>(pageData.Wheres);
            foreach (var item in listWhere)
            {
                if (item.name == "deviceNo")
                    deviceNo = item.value;
                else if (item.name == "online" && !string.IsNullOrWhiteSpace(item.value))
                    isOnline = int.Parse(item.value);
                else if (item.name == "CreateDate" && item.displayType == "thanorequal")
                    startTime = DateTime.Parse(item.value);
                else if (item.name == "CreateDate" && item.displayType == "lessorequal")
                    endTime = DateTime.Parse(item.value);
            }

            int pageSize = pageData.Rows; // 每页显示的数量
            int pageIndex = pageData.Page; // 当前页码
            string sort = pageData.Sort;

            var querys = repository.FindAsIQueryable(r => 1 == 1).WhereIF(startTime.HasValue, m => m.CreateDate >= startTime.Value)
                .WhereIF(endTime.HasValue, m => m.CreateDate <= endTime.Value)
                .WhereIF(!string.IsNullOrWhiteSpace(deviceNo), d => d.deviceNo.Contains(deviceNo))
                .WhereIF(isOnline != null, d => d.online == isOnline);

            var allowIds = AppSetting.QueryAllDeviceUserIds;
            if (!string.IsNullOrWhiteSpace(allowIds))
            {
                var userId = UserContext.Current.UserId;
                var strIds = allowIds.Split(',');
                var ids = Array.ConvertAll(strIds, int.Parse);
                if (!ids.Contains(userId))
                {
                    var sharpModels = _repositorySharp.FindAsIQueryable(r => 1 == 1).ToList();
                    List<deviceShare> shares = new List<deviceShare>();
                    foreach (var sharpModel in sharpModels)
                    {
                        var userIds = sharpModel.shareUserIds.Split(",");
                        if (userIds.Contains(userId.ToString()))
                        {
                            shares.Add(sharpModel);
                        }
                    }
                    var deviceIdList = shares.Select(r => r.deviceId).ToList();
                    querys = querys.Where(d => d.CreateID == userId || deviceIdList.Contains(d.id));
                }
            }
            var dtos = querys;
            if (pageData.Order == "asc")
                dtos = querys.OrderBy(d => d.online).OrderBy(d => d.deviceNo).OrderBy(d => d.runtime);
            else
                dtos = querys.OrderByDescending(d => d.online).OrderByDescending(d => d.deviceNo).OrderByDescending(d => d.runtime);
           

            var models = dtos.ToList();
            var deviceNos = models.Select(d => d.deviceNo);

            foreach (var model in models)
            {
                //var entity = items.OrderByDescending(m => m.uploadTime).First();
                var entity = _mongoDbContext.MeasureInfo.OrderByDescending(m => m.uploadTime).FirstOrDefault(m => m.deviceNo == model.deviceNo);
                if (entity != null)
                {
                    model.targetDistance1 = entity.targetDistance1;
                    model.targetDistance2 = entity.targetDistance2;
                    model.targetDistance3 = entity.targetDistance3;
                    model.targetSnr1 = entity.targetSnr1;
                    model.targetSnr2 = entity.targetSnr2;
                    model.targetSnr3 = entity.targetSnr3;
                }
            }

            return base.MyExport(models);
        }
        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="saveDataModel"></param>
        /// <returns></returns>
        public override WebResponseContent Add(SaveModel saveDataModel)
        {
            if (saveDataModel.MainData.DicKeyIsNullOrEmpty("deviceNo"))
            {
                return new WebResponseContent().Error("设备编号不能为空!");
            }
            string deviceNo = saveDataModel.MainData["deviceNo"].ToString();
            var head = deviceNo.Substring(0, 4);
            if (head != "HYDS" || deviceNo.Length != 19)
            {
                webResponse.Code = "-1";
                webResponse.Message = "新增失败,设备格式不正确。格式请按如下【HYDS20240504-100-01】，请按格式填写！";
                return webResponse.Error(webResponse.Message);
            }
            if (base.repository.Exists(x => x.deviceNo == deviceNo))
                return new WebResponseContent().Error("设备编号:" + deviceNo + "已存在");
            var deviceId = Guid.NewGuid();
            var userId = UserContext.Current.UserId;
            deviceinfo model = new deviceinfo()
            {
                id = deviceId,
                deviceNo = deviceNo,
                CreateDate = DateTime.Now,
                online = 0,
                CreateID = userId,
                Creator = UserContext.Current.UserName
            };
            if (!_repositoryDetail.Exists(x => x.deviceNo == deviceNo))
            {
                devicedetail modelDetail = new devicedetail()
                {
                    id = Guid.NewGuid(),
                    device_id = deviceId,
                    deviceNo = deviceNo,
                    CreateID = userId,
                };
                _repositoryDetail.Add(modelDetail);
                _repositoryDetail.SaveChanges();
            }
            if(!_repositoryBoardInfo.Exists(x => x.deviceNo == deviceNo))
            {
                boardInfo modelBoardInfo = new boardInfo()
                {
                    id = Guid.NewGuid(),
                    device_id = deviceId,
                    CreateID = userId,
                    deviceNo = deviceNo,
                };
                _repositoryBoardInfo.Add(modelBoardInfo);
                _repositoryBoardInfo.SaveChanges();
            }
            repository.Add(model);
            repository.SaveChanges();
            return webResponse.OK("创建成功");
        }
        /// <summary>
        /// 删除(只有一条)
        /// </summary>
        /// <param name="keys">删除的行的主键</param>
        /// <param name="delList">删除时是否将明细也删除</param>
        /// <returns></returns>
        public override WebResponseContent Del(object[] keys, bool delList = true)
        {
            if (keys.Length < 0)
            {
                webResponse.Error("请选择删除的数据");
            }

            var guid = keys[0].ToString();
            var model =  repository.FindFirst(d=>d.id.ToString() == guid);
            if (model != null)
            {
                var userId = UserContext.Current.UserId;
                var allowIds = AppSetting.QueryAllDeviceUserIds;
                if (model.CreateID != UserContext.Current.UserId && !allowIds.Contains(userId.ToString()))
                {
                    return webResponse.Error("非自己创建的设备无法删除!");
                }
                repository.Delete(model);
                repository.SaveChanges();

                var detail = _repositoryDetail.FindAsIQueryable(d => d.deviceNo == model.deviceNo).ToList();
                foreach (var item in detail)
                {
                    _repositoryDetail.Delete(item);
                    _repositoryDetail.SaveChanges();
                }
                var boardInfo = _repositoryBoardInfo.FindAsIQueryable(d => d.deviceNo == model.deviceNo).ToList();
                foreach (var item in boardInfo)
                {
                    _repositoryBoardInfo.Delete(item);
                    _repositoryBoardInfo.SaveChanges();
                }
            }
            return  webResponse.OK("删除成功");
        }
        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        public override WebResponseContent Import(List<IFormFile> files)
        {
            //设置导入的字段(如果指定了上面导出模板的字段，这里配置应该与上面DownLoadTemplate方法里配置一样)
            //如果不设置导入的字段DownLoadTemplateColumns,默认显示所有界面上所有可以看到的字段
            DownLoadTemplateColumns = x => new { x.deviceNo };


            /// <summary>
            /// 2022.06.20增加原生excel读取方法(导入时可以自定义读取excel内容)
            /// string=当前读取的excel单元格的值
            /// ExcelWorksheet=excel对象
            /// ExcelRange当前excel单元格对象
            /// int=当前读取的第几行
            /// int=当前读取的第几列
            /// string=返回的值
            /// </summary>
            ImportOnReadCellValue = (string value, ExcelWorksheet worksheet, ExcelRange excelRange, int rowIndex, int columnIndex) =>
            {
                string 表头列名 = worksheet.Cells[1, columnIndex].Value?.ToString();
                //这里可以返回处理后的值，值最终写入到model字段上
                return value;
            };

            //导入保存前处理(可以对list设置新的值)
            ImportOnExecuting = (List<deviceinfo> list) =>
            {
                bool formatIsOk = true;
                string[] deviceNos = new string[list.Count];
                //设备编号格式!HYDS20240504-100-01#   ---总长度21
                for (int i = 0; i < list.Count; i++)
                {
                    var deviceNo = list[i].deviceNo;
                    if (string.IsNullOrEmpty(deviceNo) || deviceNo.Length != 19)
                    {
                        formatIsOk = false;
                        break;
                    }
                    var head = deviceNo.Substring(0, 4);
                    if (head != "HYDS")
                    {
                        formatIsOk = false;
                        break;
                    }
                    deviceNos[i] = list[i].deviceNo;
                    list[i].id = Guid.NewGuid();
                    list[i].online = 0;
                    list[i].CreateID = UserContext.Current.UserId;
                    list[i].Creator = UserContext.Current.UserName;
                    list[i].CreateDate = DateTime.Now;
                }
                if(!formatIsOk)
                {
                    webResponse.Code = "-1";
                    webResponse.Message = "设备格式不正确，导入失败。格式请按如下【HYDS20240504-100-01】，请按格式填写！";
                    return webResponse.Error(webResponse.Message);
                }
                if( repository.Exists(r => deviceNos.Contains(r.deviceNo)))
                {
                    webResponse.Code = "-1";
                    webResponse.Message = "文件中存在已注册的设备号，改入失败，请检测文件！";
                    return webResponse.Error(webResponse.Message);
                }

                //设置webResponse.Code = "-1"会中止后面代码执行，与返回 webResponse.Error()一样，区别在于前端提示的是成功或失败
                //webResponse.Code = "-1";
                //webResponse.Message = "测试强制返回";
                //return webResponse.OK("ok");
                return webResponse.OK("导入成功");
            };

            //导入后处理(已经写入到数据库了)
            ImportOnExecuted = (List<deviceinfo> list) =>
            {
                foreach (deviceinfo deviceinfo in list)
                {
                    if(!_repositoryDetail.Exists(x=>x.deviceNo == deviceinfo.deviceNo))
                    {
                        devicedetail modelDetail = new devicedetail()
                        {
                            id = Guid.NewGuid(),
                            device_id = deviceinfo.id,
                            deviceNo = deviceinfo.deviceNo,
                            CreateID = deviceinfo.CreateID,
                        };
                        _repositoryDetail.Add(modelDetail);
                        _repositoryDetail.SaveChanges();
                    }
                    if(!_repositoryBoardInfo.Exists(x=>x.deviceNo == deviceinfo.deviceNo))
                    {
                        boardInfo modelBoardInfo = new boardInfo()
                        {
                            id = Guid.NewGuid(),
                            device_id = deviceinfo.id,
                            deviceNo = deviceinfo.deviceNo,
                            CreateID = deviceinfo.CreateID,
                        };
                        _repositoryBoardInfo.Add(modelBoardInfo);
                        _repositoryBoardInfo.SaveChanges();
                    }
                }
                return webResponse.OK("导入成功");
            };
            return base.Import(files);
        }
        /// <summary>
        /// 上传升级文件进行设备升级
        /// </summary>
        /// <param name="formData">参数</param>
        /// <param name="files">升级文件</param>
        /// <returns></returns>
        public WebResponseContent UploadFile(IFormCollection formData, IFormFile file)
        {
            var dir = AppSetting.UpgradeDir;
            string dicPath = dir+ $"/Upload/{DateTime.Now.ToString("yyyMMdd")}/";
            if (!Directory.Exists(dicPath)) Directory.CreateDirectory(dicPath);
            //dicPath = $"{dicPath}{Guid.NewGuid().ToString()}_{file.FileName}";
            dicPath = $"{dicPath}{DateTime.Now.ToString("yyyyMMddHHmmssfff")}_{file.FileName}";
            var id = formData["id"];
            var upType = formData["upType"];
            var deviceNo = formData["deviceNo"];
            var deviceNoStr = deviceNo.ToString();

            var model = _mongoDbContext.DeviceUpgrade.FirstOrDefault(d=>d.DeviceNo == deviceNoStr);
            if (model != null && model.IsUpgradeIng)
            {
                webResponse.Code = "-1";
                webResponse.Message = "设备升级中，请勿重复升级！";
                return webResponse.Error(webResponse.Message);
            }

            using (var stream = new FileStream(dicPath, FileMode.Create))
            {
                file.CopyTo(stream);
            }
            if (!File.Exists(dicPath))
            {
                webResponse.Code = "-1";
                webResponse.Message = "升级文件获取失败，请重新上传！";
                return webResponse.Error(webResponse.Message);
            }
            UpgradeDto dto = new UpgradeDto()
            {
                Id = id,
                UpType = upType,
                DeviceNo = deviceNo,
                filePath = dicPath
            };
            var jsonStr = JsonConvert.SerializeObject(dto);
            var url = AppSetting.TcpServiceApiUrl + "Radar/api/DeviceUpgrade";
            var resStr = HttpPost(url, jsonStr).Result;
            if (string.IsNullOrEmpty(resStr))
            {
                return webResponse.Error("升级失败，请重试！");
            }
            var res = JsonConvert.DeserializeObject<ApiResult>(resStr);
            if (!res.success)
            {
                webResponse.Code = "-1";
                webResponse.Message = res.message;
                return webResponse.Error(webResponse.Message);
            }
            webResponse.Code = "1";
            webResponse.Message = "升级文件上传成功，正在请求升级...";
            return webResponse.OK("文件上传成功");
        }
        /// <summary>
        /// 取消升级
        /// </summary>
        /// <param name="deviceNo">设备号</param>
        /// <returns></returns>
        public async Task<WebResponseContent> CancelUpgrade(string deviceNo)
        {
            var model = _mongoDbContext.DeviceUpgrade.Where(d=>d.DeviceNo == deviceNo).FirstOrDefault();
            if (model == null)
            {
                return webResponse.OK(null, "该设备还未进行升级");
            }
            var url = AppSetting.TcpServiceApiUrl + "Radar/api/CancelUpgrade?deviceNo=" + deviceNo;
            var resStr = HttpGet(url).Result;

            return webResponse.OK(null, resStr);
        }
        #region HTTP请求
        /// <summary>
        /// http Get请求
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public async Task<string> HttpGet(string url)
        {
            string resStr = "";
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    // 发送GET请求
                    HttpResponseMessage response = await client.GetAsync(url);
                    // 确保请求成功
                    response.EnsureSuccessStatusCode();

                    // 读取响应内容作为字符串
                    resStr = await response.Content.ReadAsStringAsync();
                }
                catch (HttpRequestException e)
                {
                    Console.WriteLine("Message :{0} ", e.Message);
                }
            }
            return resStr;
        }
        /// <summary>
        /// Http Post请求(参数Json)
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="param">请求参数(json)</param>
        /// <returns></returns>
        public async Task<string> HttpPost(string url, string param)
        {
            string resStr = "";
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    if (!string.IsNullOrEmpty(param))
                    {
                        // 将JSON字符串转换为HttpContent对象，并设置Content-Type为application/json
                        HttpContent content = new StringContent(param, Encoding.UTF8, "application/json");
                        // 发送POST请求
                        HttpResponseMessage response = await client.PostAsync(url, content);
                        // 确保请求成功
                        response.EnsureSuccessStatusCode();
                        resStr = await response.Content.ReadAsStringAsync();
                    }
                    else
                    {
                        HttpResponseMessage response = await client.PostAsync(url, null);
                        // 确保请求成功
                        response.EnsureSuccessStatusCode();
                        // 读取响应内容
                        resStr = await response.Content.ReadAsStringAsync();
                    }
                }
                catch (HttpRequestException e)
                {
                    Console.WriteLine("Exception Caught!");
                    Console.WriteLine("Message :{0} ", e.Message);
                }
            }
            return resStr;
        }
        #endregion HTTP请求
    }
}
